package controller;

import java.util.ArrayList;

import util.JsonUtil;
import manager.BidMgr;
import manager.CompletedCourseMgr;
import manager.CourseMgr;
import manager.CoursePreRequisiteMgr;
import manager.SectionMgr;
import manager.SectionStudentMgr;
import manager.StudentMgr;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import entity.Bid;
import entity.Course;
import entity.Section;
import entity.Student;
import exception.ValidationError;

/**
 * @author mohameds.2012, sheryl.tay.2012
 * 
 */
public class DumpCtrl {

	private StudentMgr studentMgr;
	private CourseMgr courseMgr;
	private CoursePreRequisiteMgr coursePrerequisiteMgr;
	private CompletedCourseMgr completedCourseMgr;
	private SectionMgr sectionMgr;
	private BidMgr bidMgr;
	private SectionStudentMgr sectionStudentMgr;
	private RoundCtrl roundCtrl;

	public DumpCtrl() {
		studentMgr = new StudentMgr();
		courseMgr = new CourseMgr();
		coursePrerequisiteMgr = new CoursePreRequisiteMgr();
		completedCourseMgr = new CompletedCourseMgr();
		sectionMgr = new SectionMgr();
		bidMgr = new BidMgr();
		sectionStudentMgr = new SectionStudentMgr();
		roundCtrl = new RoundCtrl();
	}

	public JSONObject dumpTable() {
		JSONObject dumpTableJsonObj = new JSONObject();

		dumpTableJsonObj.put("status", "success");
		dumpTableJsonObj.put("course", dumpCourseTable());
		dumpTableJsonObj.put("section", dumpSectionTable());
		dumpTableJsonObj.put("student", dumpStudentTable());
		dumpTableJsonObj.put("prerequisite", dumpPrerequisiteTable());
		dumpTableJsonObj.put("bid", dumpBidTable());
		dumpTableJsonObj.put("completed-courses", dumpCompletedCourseTable());
		dumpTableJsonObj.put("section-students", dumpSectionStudentTable());

		return dumpTableJsonObj;
	}

	private JSONArray dumpCourseTable() {

		JSONArray dumpCourseJsonArray = new JSONArray();

		ArrayList<Course> courses = courseMgr.retrieveAllCourses();

		for (Course eachCourse : courses) {

			JSONObject dumpCourseJsonObj = new JSONObject();

			dumpCourseJsonObj.put("course", eachCourse.getCourseCode());
			dumpCourseJsonObj.put("school", eachCourse.getSchool());
			dumpCourseJsonObj.put("title", eachCourse.getTitle());
			dumpCourseJsonObj.put("description", eachCourse.getDescription());
			dumpCourseJsonObj.put("exam date", eachCourse.getExamDate());
			dumpCourseJsonObj.put("exam start", eachCourse.getExamStartTime());
			dumpCourseJsonObj.put("exam end", eachCourse.getExamEndTime());

			dumpCourseJsonArray.add(dumpCourseJsonObj);

		}

		return dumpCourseJsonArray;
	}

	private JSONObject dumpStudentTable() {

		JSONArray dumpStudentJsonArray = new JSONArray();

		ArrayList<Student> students = studentMgr.retrieveAllStudents();

		for (Student eachStudent : students) {

			JSONObject studentJsonObj = new JSONObject();

			studentJsonObj.put("userid", eachStudent.getUserId());
			studentJsonObj.put("password", eachStudent.getPassword());
			studentJsonObj.put("name", eachStudent.getName());
			studentJsonObj.put("school", eachStudent.getSchool());
			studentJsonObj.put("edollar", eachStudent.getEdollar());

			dumpStudentJsonArray.add(studentJsonObj);

		}

		JSONObject jsonObj = new JSONObject();
		jsonObj.put("student", dumpStudentJsonArray);

		return jsonObj;
	}

	private JSONArray dumpSectionTable() {

		JSONArray dumpSectionJsonArray = new JSONArray();

		ArrayList<Section> sections = sectionMgr.retrieveAllSections();

		for (Section eachSection : sections) {
			JSONObject dumpSectionJsonObj = new JSONObject();

			dumpSectionJsonObj.put("course", eachSection.getCourse()
					.getCourseCode());
			dumpSectionJsonObj.put("section", eachSection.getSectionCode());
			dumpSectionJsonObj.put("day", eachSection.getDayOfWeek());
			dumpSectionJsonObj.put("start", eachSection.getStartTime());
			dumpSectionJsonObj.put("end", eachSection.getEndTime());
			dumpSectionJsonObj.put("instructor", eachSection.getInstructor());
			dumpSectionJsonObj.put("venue", eachSection.getVenue());
			dumpSectionJsonObj.put("size", eachSection.getSize());

			dumpSectionJsonArray.add(dumpSectionJsonObj);
		}

		return dumpSectionJsonArray;
	}

	private JSONArray dumpBidTable() {

		JSONArray bidJsonArray = new JSONArray();

		ArrayList<Bid> bids = bidMgr.retrieveAllBids();

		for (Bid eachBid : bids) {

			JSONObject bidJsonObj = new JSONObject();

			bidJsonObj.put("userId", eachBid.getStudent().getUserId());
			bidJsonObj.put("bidamount", eachBid.getBidAmount());
			bidJsonObj.put("course", eachBid.getSection().getCourse()
					.getCourseCode());
			bidJsonObj.put("section", eachBid.getSection().getSectionCode());

		}

		return bidJsonArray;
	}

	private JSONArray dumpSectionStudentTable() {

		JSONArray sectionStudentJsonArray = new JSONArray();

		ArrayList<Bid> successfulBids = sectionStudentMgr
				.retrieveAllSuccessfulBids();

		for (Bid eachBid : successfulBids) {
			JSONObject bidJsonObj = new JSONObject();

			bidJsonObj.put("userId", eachBid.getStudent().getUserId());
			bidJsonObj.put("course", eachBid.getSection().getCourse()
					.getCourseCode());
			bidJsonObj.put("section", eachBid.getSection().getSectionCode());
			bidJsonObj.put("bidAmount", eachBid.getBidAmount());

			sectionStudentJsonArray.add(bidJsonObj);
		}

		return sectionStudentJsonArray;
	}

	private JSONArray dumpPrerequisiteTable() {

		JSONArray prerequisiteJsonArray = new JSONArray();

		ArrayList<Course> courses = coursePrerequisiteMgr
				.retrieveAllCoursesWithPrerequisite();

		for (Course eachCourse : courses) {
			JSONObject prerequisiteJsonObj = new JSONObject();

			ArrayList<Course> prerequisites = coursePrerequisiteMgr
					.retrievePreRequisitesForCourse(eachCourse.getCourseCode());

			for (Course eachPrerequisite : prerequisites) {

				prerequisiteJsonObj.put("course", eachCourse.getCourseCode());
				prerequisiteJsonObj.put("prerequisite",
						eachPrerequisite.getCourseCode());

				prerequisiteJsonArray.add(prerequisiteJsonObj);

			}
		}

		return prerequisiteJsonArray;
	}

	private JSONArray dumpCompletedCourseTable() {

		JSONArray completedCourseJsonArray = new JSONArray();

		ArrayList<Course> courses = completedCourseMgr
				.retrieveAllCompletedCourses();

		for (Course eachCourse : courses) {
			JSONObject completedCourseJsonObj = new JSONObject();

			ArrayList<Student> students = completedCourseMgr
					.retrieveStudentsWhoCompletedCourse(eachCourse
							.getCourseCode());

			for (Student eachStudent : students) {

				completedCourseJsonObj.put("userid", eachStudent.getUserId());
				completedCourseJsonObj
						.put("course", eachCourse.getCourseCode());

				completedCourseJsonArray.add(completedCourseJsonObj);

			}
		}

		return completedCourseJsonArray;
	}

	/**
	 * Retrieves the bidding information of a specific section for the current
	 * bidding round. If no bidding rounds are active, the information for the
	 * most recently concluded round is dumped.
	 * 
	 * @param courseCode
	 *            course code of the course to which the section belongs to
	 * @param sectionCode
	 *            section code of the section
	 * @return JSON object containing the bids data
	 * 
	 * @author mohameds.2012, sheryl.tay.2012
	 */
	public JSONObject dumpBid(String courseCode, String sectionCode) {
		JSONObject bidsJsonObj = new JSONObject();
		JSONArray bidsJsonArray = new JSONArray();

		if (roundCtrl.getCurrentRound().isRoundOpen()) {
			// dump bid for current round
			ArrayList<Bid> bids = bidMgr.retrieveBidsForSection(courseCode,
					sectionCode);

			for (int i = 0; i < bids.size(); i++) {
				Bid eachBid = bids.get(i);

				JSONObject bidJsonObj = new JSONObject();
				bidJsonObj.put("row", i + 1);
				bidJsonObj.put("userid", eachBid.getStudent().getUserId());
				bidJsonObj.put("amount", eachBid.getBidAmount());

				bidsJsonArray.add(bidJsonObj);
			}

		} else {
			// dump bid results for the most recently concluded round
			ArrayList<Bid> bids = bidMgr.retrieveBidResultsForSection(
					courseCode, sectionCode);

			for (int i = 0; i < bids.size(); i++) {
				Bid eachBid = bids.get(i);

				JSONObject bidJsonObj = new JSONObject();
				bidJsonObj.put("row", i + 1);
				bidJsonObj.put("userid", eachBid.getStudent().getUserId());
				bidJsonObj.put("amount", eachBid.getBidAmount());
				bidJsonObj.put("result", eachBid.getBidResult());

				bidsJsonArray.add(bidJsonObj);
			}

		}

		bidsJsonObj.put("status", "success");
		if (!bidsJsonArray.isEmpty()) {
			bidsJsonObj.put("bids", bidsJsonArray);
		}

		return bidsJsonObj;
	}

	/**
	 * Retrieves the information of a specific user.
	 * 
	 * @param userId
	 * @return JSON object containing the user data
	 * 
	 * @author mohameds.2012, sheryl.tay.2012
	 */
	public JSONObject dumpUser(String userId) {
		JSONObject studentJsonObj = new JSONObject();

		try {
			Student user = studentMgr.retrieveStudentForUserId(userId);

			studentJsonObj.put("status", "success");
			studentJsonObj.put("userid", user.getUserId());
			studentJsonObj.put("password", user.getPassword());
			studentJsonObj.put("name", user.getName());
			studentJsonObj.put("school", user.getSchool());
			studentJsonObj.put("edollar", user.getEdollar());

		} catch (ValidationError e) {
			return JsonUtil.newJsonErrorResponse(e.toJsonArray());
		}

		return studentJsonObj;
	}

	/**
	 * Retrieves the information for a section, and it's enrolled students.
	 * During round 2, this will return the enrolled students bid successfully
	 * in round 1. After round 2 is closed, this will return the enrolled
	 * students who bid successfully in round 1 & 2.
	 * 
	 * @param courseCode
	 *            course code of the course to which the section belongs to
	 * @param sectionCode
	 *            section code of the section
	 * @return JSON object containing students
	 * 
	 * @author huangjm.2012, huiwensong.2012
	 */
	public JSONObject dumpSection(String courseCode, String sectionCode) {
		JSONArray studentsJsonArray = new JSONArray();

		ArrayList<Bid> successfulBids = sectionStudentMgr
				.retrieveSuccessfulBidsForSection(courseCode, sectionCode);
		JSONObject studentsJsonObj = new JSONObject();

		JSONObject studentJsonObj;

		for (Bid eachBid : successfulBids) {

			studentJsonObj = new JSONObject();
			studentJsonObj.put("userid", eachBid.getStudent().getUserId());
			studentJsonObj.put("amount", eachBid.getBidAmount());

			studentsJsonArray.add(studentJsonObj);
		}

		studentsJsonObj.put("status", "success");
		studentsJsonObj.put("students", studentsJsonArray);

		return studentsJsonObj;
	}

}
